package com.yeyks.apppay.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yeyks.apppay.service.WXAppPayService;
import com.yeyks.exception.ServiceException;
import com.yeyks.model.RefundRequestNo;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConfig;
import com.github.wxpay.sdk.WXPayUtil;
import com.yeyks.exception.ServiceException;
import com.yeyks.model.RefundRequestNo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @Author fuchangshuai
 * @date 2019/3/4 2:34 PM
 */
@Service
@Slf4j
public class WXAppPayServiceImpl implements WXAppPayService {
    @Autowired
    private WXPayConfig wxPayConfig;

    @Value("${wx.app.key}")
    String key;

    @Value("${wx.app.notifyUrl}")
    String notify_url;

    @Value("${wx.app.vipNotifyUrl}")
    String vip_notify_url;

    @Value("${wx.app.rechangeNotifyUrl}")
    String rechangeNotifyUrl;

    @Value("${wx.app.appId}")
    String appId;

    @Value("${wx.app.mchId}")
    String mch_id;

    @Override
    public String pay(Integer totalFee, String orderNo, String ip) {
        log.info("微信app支付");
        Map<String, String> map = wxPay(orderNo, totalFee, ip);
        return JSON.toJSONString(map);
    }

    /**
     * JSAPI支付
     *
     * @param orderNo
     * @param totalFee
     * @param ip
     * @return
     */
    @Override
    public String jsApiPay(Integer totalFee, String orderNo, String ip, String openid) {
        try {
            Map<String, String> map = new LinkedHashMap<>();
            String body = "订单支付";
            String nonce_str = WXPayUtil.generateNonceStr();
            String total_fee = String.valueOf(totalFee);
            map.put("body", body);
            map.put("nonce_str", nonce_str);
            map.put("out_trade_no", orderNo);
            map.put("total_fee", total_fee);
            map.put("spbill_create_ip", ip);
            map.put("notify_url", "");
            map.put("trade_type", "JSAPI");
            WXPay pay = new WXPay(wxPayConfig);
            Map<String, String> returnMap = pay.unifiedOrder(map);
            Map<String, String> resultMap = new LinkedHashMap<>();
            resultMap.put("appid", appId);
            resultMap.put("noncestr", nonce_str);
            resultMap.put("package", "Sign=WXPay");
            resultMap.put("partnerid", mch_id);
            resultMap.put("prepayid", returnMap.get("prepay_id"));
            resultMap.put("timestamp", System.currentTimeMillis() / 1000 + "");
            StringBuilder result = new StringBuilder();
            for (Map.Entry<String, String> entry : resultMap.entrySet()) {
                result.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
            result.append("key=").append(key);
            resultMap.put("sign", DigestUtils.md5Hex(result.toString()).toUpperCase());

            return JSONObject.toJSONString(resultMap);
        } catch (Exception e) {
            log.info("微信支付失败{}", Arrays.toString(e.getStackTrace()));
            throw new ServiceException("微信支付异常");
        }

    }

    @Override
    public Boolean refund(Integer refundFee, Integer totalFee, String orderNo) {
        log.info("微信退款");
        return wxRefund(refundFee, totalFee, orderNo);
    }

    private Map<String, String> wxPay(String orderNO, Integer payAmount, String ip) {
        try {
            Map<String, String> map = new LinkedHashMap<>();
            String body = "订单支付";
            String nonce_str = WXPayUtil.generateNonceStr();
            String total_fee = String.valueOf(payAmount);
            map.put("body", body);
            map.put("nonce_str", nonce_str);
            map.put("out_trade_no", orderNO);
            map.put("total_fee", total_fee);
            map.put("spbill_create_ip", ip);
            map.put("notify_url", notify_url);
            map.put("trade_type", "APP");
            WXPay pay = new WXPay(wxPayConfig);
            Map<String, String> returnMap = pay.unifiedOrder(map);
            Map<String, String> resultMap = new LinkedHashMap<>();
            resultMap.put("appid", appId);
            resultMap.put("noncestr", nonce_str);
            resultMap.put("package", "Sign=WXPay");
            resultMap.put("partnerid", mch_id);
            resultMap.put("prepayid", returnMap.get("prepay_id"));
            resultMap.put("timestamp", System.currentTimeMillis() / 1000 + "");
            StringBuilder result = new StringBuilder();
            for (Map.Entry<String, String> entry : resultMap.entrySet()) {
                result.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
            result.append("key=").append(key);
            resultMap.put("sign", DigestUtils.md5Hex(result.toString()).toUpperCase());

            return resultMap;
        } catch (Exception e) {
            log.info("微信支付失败{}", Arrays.toString(e.getStackTrace()));
            throw new ServiceException("微信支付异常");
        }
    }

    @Override
    public String vipPay(Integer totalFee, String orderNo, String ip) {
        Map<String, String> map = pay(orderNo, totalFee, ip, vip_notify_url);
        return JSON.toJSONString(map);
    }

    @Override
    public String rechangePay(Integer totalFee, String orderNo, String ip) {
        Map<String, String> map = pay(orderNo, totalFee, ip, rechangeNotifyUrl);
        return JSON.toJSONString(map);
    }

    public Map<String, String> pay(String orderNO, Integer payAmount, String ip, String notifyUrl) {
        try {
            Map<String, String> map = new LinkedHashMap<>();
            String body = "订单支付";
            String nonce_str = WXPayUtil.generateNonceStr();
            String total_fee = String.valueOf(payAmount);
            map.put("body", body);
            map.put("nonce_str", nonce_str);
            map.put("out_trade_no", orderNO);
            map.put("total_fee", total_fee);
            map.put("spbill_create_ip", ip);
            map.put("notify_url", notifyUrl);
            map.put("trade_type", "APP");
            WXPay pay = new WXPay(wxPayConfig);
            Map<String, String> returnMap = pay.unifiedOrder(map);
            Map<String, String> resultMap = new LinkedHashMap<>();
            resultMap.put("appid", appId);
            resultMap.put("noncestr", nonce_str);
            resultMap.put("package", "Sign=WXPay");
            resultMap.put("partnerid", mch_id);
            resultMap.put("prepayid", returnMap.get("prepay_id"));
            resultMap.put("timestamp", System.currentTimeMillis() / 1000 + "");
            StringBuilder result = new StringBuilder();
            for (Map.Entry<String, String> entry : resultMap.entrySet()) {
                result.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
            result.append("key=").append(key);
            resultMap.put("sign", DigestUtils.md5Hex(result.toString()).toUpperCase());

            return resultMap;
        } catch (Exception e) {
            log.info("微信支付失败{}", Arrays.toString(e.getStackTrace()));
            throw new ServiceException("微信支付异常");
        }
    }

    private Boolean wxRefund(Integer refundFee, Integer totalFee, String orderNo) {
        try {
            String outRequestNo = orderNo + RefundRequestNo.outNo;
            String refundAmount = String.valueOf(refundFee);
            String totalAmount = String.valueOf(totalFee);
            Map<String, String> map = new LinkedHashMap<>();
            String nonce_str = WXPayUtil.generateNonceStr();
            map.put("nonce_str", nonce_str);
            map.put("out_trade_no", orderNo);
            map.put("out_refund_no", outRequestNo);
            map.put("total_fee", totalAmount);
            map.put("refund_fee", refundAmount);
            WXPay pay = new WXPay(wxPayConfig);
            Map<String, String> resutlMap = pay.refund(map);
            String resultCode = resutlMap.get("result_code") == null ? "FAIL" : resutlMap.get("result_code");
            String resultRefundFee = resutlMap.get("refund_fee") == null ? "FAIL" : resutlMap.get("refund_fee");
            if ("SUCCESS".equals(resultCode) && resultRefundFee.equals(refundAmount)) {
                return true;
            }
        } catch (Exception e) {
            log.info("微信退款失败{}", Arrays.toString(e.getStackTrace()));
            return false;
        }
        return false;
    }

//    public static void main(String[] args) throws Exception {
//
//        WXPay pay = new WXPay(new WXPayConfigImpl());
//
//        Map<String, String> data = new HashMap<String, String>();
//        data.put("body", "腾讯充值中心-QQ会员充值");
//        data.put("out_trade_no", "2016090910595900000123");
//        data.put("device_info", "");
//        data.put("fee_type", "CNY");
//        data.put("total_fee", "1");
//        data.put("spbill_create_ip", "192.168.1.1");
//        data.put("notify_url", "http://www.example.com/wxpay/notify");
//        data.put("trade_type", "JSAPI");  // 此处指定为扫码支付
//        data.put("product_id", "12");
//        data.put("openid", "oCAEs0wlUq55Bd-Q3E6U1Y7wca_o");
//
//        try {
//            Map<String, String> resp = pay.unifiedOrder(data);
//            System.out.println(resp);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }
}
